package top.chmin.project.cloud.builder;

import cn.hutool.core.util.StrUtil;
import org.springframework.stereotype.Component;

import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * chmin
 * 2023/12/19 14:33
 * cloud-builder
 */
@Component
public class PageUiBuilder implements Builder {

    @Override
    public void build(BuilderConfig config) {
        String source = """
                <script lang="ts" setup>
                                
                import {onMounted, reactive} from "vue";
                import {NButton, NSpace} from "naive-ui";
                import {BasePage, completePage} from "../../%sts/type";
                import {replace, stampToDatetimeText} from "../../%sts/util";
                import {extraConfig} from "../#e.fieldName#PageConfig";
                import {#e.fieldName#SearchInit} from "./#e.fieldName#SearchInit";
                import {#e.fieldName#SaveInit} from "./#e.fieldName#SaveInit";
                import {#e.fieldName#UpdateInit} from "./#e.fieldName#UpdateInit";
                import {#e.fieldName#DetailInit} from "./#e.fieldName#DetailInit";
                import {#e.fieldName#ColumnInit} from "./#e.fieldName#ColumnInit";
                                
                let page: BasePage = reactive(new BasePage())
                completePage(page)
                #e.fieldName#SearchInit(page)
                #e.fieldName#SaveInit(page)
                #e.fieldName#UpdateInit(page)
                #e.fieldName#DetailInit(page)
                #e.fieldName#ColumnInit(page)
                page.url = {
                  save: '/au/#e.fieldName#/save',
                  updateById: '/au/#e.fieldName#/updateById',
                  deleteById: '/au/#e.fieldName#/deleteById',
                  selectById: '/au/#e.fieldName#/selectById',
                  selectPage: '/au/#e.fieldName#/selectPage'
                }
                                
                extraConfig(page)
                                
                onMounted(() => {
                  page.loadData()
                })
                </script>
                                
                <template>
                  <n-card title="#e.remark#">
                    <n-form
                        v-bind="page.search"
                    >
                      <n-grid :cols="24" :x-gap="24">
                        <template v-for="input in page.search.formInputs.filter(i => i.exist)">
                          <n-form-item-gi v-bind="input" v-if="input.inputType == 'text'">
                            <n-input v-model:value="page.search.model[input.path]" v-bind="input"/>
                          </n-form-item-gi>
                          <n-form-item-gi v-bind="input" v-if="input.inputType == 'number'">
                            <n-input-number v-model:value="page.search.model[input.path]" v-bind="input"/>
                          </n-form-item-gi>
                          <n-form-item-gi v-bind="input" v-if="input.inputType == 'select'">
                            <n-select v-model:value="page.search.model[input.path]" v-bind="input"/>
                          </n-form-item-gi>
                          <n-form-item-gi v-bind="input" v-if="input.inputType == 'date'">
                            <n-date-picker v-model:value="page.search.model[input.path]" v-bind="input"/>
                          </n-form-item-gi>
                          <n-form-item-gi v-bind="input" v-if="input.inputType == 'datetime'">
                            <n-date-picker v-model:value="page.search.model[input.path]" v-bind="input" type="datetime"/>
                          </n-form-item-gi>
                          <n-form-item-gi v-bind="input" v-if="input.inputType == 'dateRange'">
                            <n-date-picker v-model:value="page.search.model[input.path]" v-bind="input" type="daterange"/>
                          </n-form-item-gi>
                          <n-form-item-gi v-bind="input" v-if="input.inputType == 'datetimeRange'">
                            <n-date-picker v-model:value="page.search.model[input.path]" v-bind="input" type="datetimerange"/>
                          </n-form-item-gi>
                          <n-form-item-gi v-bind="input" v-if="input.inputType == 'radio'">
                            <n-radio-group v-model:value="page.search.model[input.path]" v-bind="input">
                              <n-space>
                                <n-radio v-for="o in input.options" :key="input.path" :value="o.value">
                                  {{ o.label }}
                                </n-radio>
                              </n-space>
                            </n-radio-group>
                          </n-form-item-gi>
                          <n-form-item-gi v-bind="input" v-if="input.inputType == 'checkbox'">
                            <n-checkbox-group v-model:value="page.search.model[input.path]" v-bind="input">
                              <n-space>
                                <n-checkbox v-for="o in input.options" :label="o.label" :value="o.value"/>
                              </n-space>
                            </n-checkbox-group>
                          </n-form-item-gi>
                          <n-form-item-gi v-bind="input" v-if="input.inputType == 'transfer'">
                            <n-transfer v-model:value="page.search.model[input.path]" v-bind="input"/>
                          </n-form-item-gi>
                          <n-form-item-gi v-bind="input" v-if="input.inputType == 'tag'">
                            <n-dynamic-tags v-model:value="page.search.model[input.path]" v-bind="input"/>
                          </n-form-item-gi>
                        </template>
                      </n-grid>
                                
                      <n-grid :cols="24" :x-gap="24">
                        <n-form-item-gi :span="12">
                          <n-space>
                            <template
                                v-for="btn in page.leftOperations"
                            >
                              <n-button
                                v-if="btn.exist"
                                :type="btn.type"
                                :block="btn.block"
                                :circle="btn.circle"
                                :color="btn.color"
                                :dashed="btn.dashed"
                                :disabled="btn.disabled"
                                :ghost="btn.ghost"
                                :round="btn.round"
                                :size="btn.size"
                                :text-color="btn.textColor"
                                @click="btn.click"
                              >
                                {{ btn.text }}
                              </n-button>
                            </template>
                          </n-space>
                        </n-form-item-gi>
                        <n-form-item-gi :span="12">
                          <n-space justify="end">
                            <template
                                v-for="btn in page.rightOperations"
                            >
                              <n-button
                                v-if="btn.exist"
                                :type="btn.type"
                                :block="btn.block"
                                :circle="btn.circle"
                                :color="btn.color"
                                :dashed="btn.dashed"
                                :disabled="btn.disabled"
                                :ghost="btn.ghost"
                                :round="btn.round"
                                :size="btn.size"
                                :text-color="btn.textColor"
                                @click="btn.click"
                              >
                                {{ btn.text }}
                              </n-button>
                            </template>
                          </n-space>
                        </n-form-item-gi>
                      </n-grid>
                    </n-form>
                    <n-data-table
                        :bordered="false"
                        :checked-row-keys="page.checkedRowKeys"
                        :columns="[...page.columns.filter(c => c.exist), page.operationColumn]"
                        :data="page.data"
                        :loading="page.loading"
                        :pagination="page.pagination"
                        :row-key="(row: any) => row.id"
                        remote
                        @update:sorter="page.changeSort"
                    />
                    <n-modal
                        v-model:show="page.currentModel.exist"
                        :bordered="false"
                        :mask-closable="false"
                        :style="page.currentModel.formStyle"
                        preset="card"
                        :size="page.currentModel.size"
                        :title="page.currentModel.formTitle"
                    >
                      <n-form
                          :ref="page.bind"
                          :model="page.currentModel.model"
                          :rules="page.currentModel.rules"
                          :key="page.currentModel.formKey"
                          :disabled="page.currentModel.disabled"
                          :inline="page.currentModel.inline"
                          :label-width="page.currentModel.labelWidth"
                          :label-align="page.currentModel.labelAlign"
                          :label-placement="page.currentModel.labelPlacement"
                          :require-mark-placement="page.currentModel.requireMarkPlacement"
                          :size="page.currentModel.size"
                      >
                        <n-grid :cols="24" :x-gap="24">
                          <template v-for="input in page.currentModel.formInputs.filter(i => i.exist)">
                            <n-form-item-gi v-bind="input" v-if="input.inputType == 'text'">
                              <n-input v-model:value="page.currentModel.model[input.path]" v-bind="input"/>
                            </n-form-item-gi>
                            <n-form-item-gi v-bind="input" v-if="input.inputType == 'number'">
                              <n-input-number v-model:value="page.currentModel.model[input.path]" v-bind="input"/>
                            </n-form-item-gi>
                            <n-form-item-gi v-bind="input" v-if="input.inputType == 'select'">
                              <n-select v-model:value="page.currentModel.model[input.path]" v-bind="input"/>
                            </n-form-item-gi>
                            <n-form-item-gi v-bind="input" v-if="input.inputType == 'date'">
                              <n-date-picker v-model:value="page.currentModel.model[input.path]" v-bind="input"/>
                            </n-form-item-gi>
                            <n-form-item-gi v-bind="input" v-if="input.inputType == 'datetime'">
                              <n-date-picker v-model:value="page.currentModel.model[input.path]" v-bind="input" type="datetime"/>
                            </n-form-item-gi>
                            <n-form-item-gi v-bind="input" v-if="input.inputType == 'dateRange'">
                              <n-date-picker v-model:value="page.currentModel.model[input.path]" v-bind="input" type="daterange"/>
                            </n-form-item-gi>
                            <n-form-item-gi v-bind="input" v-if="input.inputType == 'datetimeRange'">
                              <n-date-picker v-model:value="page.currentModel.model[input.path]" v-bind="input" type="datetimerange"/>
                            </n-form-item-gi>
                            <n-form-item-gi v-bind="input" v-if="input.inputType == 'radio'">
                              <n-radio-group v-model:value="page.currentModel.model[input.path]" v-bind="input">
                                <n-space>
                                  <n-radio v-for="o in input.options" :key="input.path" :value="o.value">
                                    {{ o.label }}
                                  </n-radio>
                                </n-space>
                              </n-radio-group>
                            </n-form-item-gi>
                            <n-form-item-gi v-bind="input" v-if="input.inputType == 'checkbox'">
                              <n-checkbox-group v-model:value="page.currentModel.model[input.path]" v-bind="input">
                                <n-space>
                                  <n-checkbox v-for="o in input.options" :label="o.label" :value="o.value"/>
                                </n-space>
                              </n-checkbox-group>
                            </n-form-item-gi>
                            <n-form-item-gi v-bind="input" v-if="input.inputType == 'transfer'">
                              <n-transfer v-model:value="page.currentModel.model[input.path]" v-bind="input"/>
                            </n-form-item-gi>
                            <n-form-item-gi v-bind="input" v-if="input.inputType == 'tag'">
                              <n-dynamic-tags v-model:value="page.currentModel.model[input.path]" v-bind="input"/>
                            </n-form-item-gi>
                          </template>
                        </n-grid>
                      </n-form>
                      <template #action>
                        <n-space justify="end">
                          <template
                              v-for="btn in page.currentModel.modelOperations"
                          >
                            <n-button
                              v-if="btn.exist"
                              :type="btn.type"
                              :block="btn.block"
                              :circle="btn.circle"
                              :color="btn.color"
                              :dashed="btn.dashed"
                              :disabled="btn.disabled"
                              :ghost="btn.ghost"
                              :round="btn.round"
                              :size="btn.size"
                              :text-color="btn.textColor"
                              @click="btn.click"
                            >
                              {{ btn.text }}
                            </n-button>
                          </template>
                        </n-space>
                      </template>
                    </n-modal>
                  </n-card>
                </template>
                                
                <style scoped>
                                
                </style>""".formatted(
                // import
                Stream.of(StrUtil.toUnderlineCase(config.getEntity().getClassName()).split("_"))
                        .map(s -> "../")
                        .collect(Collectors.joining()),
                Stream.of(StrUtil.toUnderlineCase(config.getEntity().getClassName()).split("_"))
                        .map(s -> "../")
                        .collect(Collectors.joining())
        );

        String fileName = "\\view\\%sauto\\%sPage.vue".formatted(
                Stream.of(StrUtil.toUnderlineCase(config.getEntity().getClassName()).split("_"))
                        .map(s -> s + "\\")
                        .collect(Collectors.joining()),
                config.getEntity().getClassName()
        );

        saveUi(config,
                fileName,
                fixContent(config.getEntity(), source),
                true
        );

    }
}
